<?php


namespace App\Utility;

use EasySwoole\Log\LoggerInterface;
use EasySwoole\EasySwoole\Config;

class Logger implements LoggerInterface
{
    private $logDir;

    function __construct(string $logDir = null)
    {
        if(empty($logDir)){
            $NewLogDir = Config::getInstance()->getConf('LOG_DIR');
            if (empty($NewLogDir)){
                $logDir = getcwd().DIRECTORY_SEPARATOR.'Log';
            }else{
                $logDir = $NewLogDir;
            }
        }
        $this->logDir = $logDir;
    }

    /**
     * 根据配置及参数获取日志需要记录的文件
     * @param string $logLevel
     * @return string
     */
    function getLogFile($logLevel = ''){
        $logPath = $this->logDir.DIRECTORY_SEPARATOR.date('Ym').DIRECTORY_SEPARATOR;
        $logType = Config::getInstance()->getConf('LOG_IS_SINGLE');
        if ($logType){
            //单文件模式，每天的所有类型的日志记录在一个日志文件中
            $logFile = $logPath.date('d').'.log';
        }else{
            //多文件模式，每天的所有类型的日志按照日志级别记录在不同的日志文件中
            $levelStr = $this->levelMap($logLevel);
            $logFile = $logPath. date('d') . '_' . strtolower($levelStr) .'.log';
        }
        return $logFile;
    }

    function log(?string $msg,int $logLevel = self::LOG_LEVEL_INFO,string $category = 'DEBUG'):string
    {
        $filePath = $this->getLogFile($logLevel);
        $path = dirname($filePath);
        !is_dir($path) && mkdir($path, 0755, true);
        $date = date('Y-m-d H:i:s');
        $levelStr = $this->levelMap($logLevel);
        $str = "[{$date}][{$category}][{$levelStr}] : [{$msg}]\n";
        file_put_contents($filePath,"{$str}",FILE_APPEND|LOCK_EX);
        return $msg;
    }

    function console(?string $msg,int $logLevel = self::LOG_LEVEL_INFO,string $category = 'DEBUG')
    {
        $date = date('Y-m-d H:i:s');
        $levelStr = $this->levelMap($logLevel);
        $temp =  $this->colorString("[{$date}][{$category}][{$levelStr}] : [{$msg}]",$logLevel)."\n";
        fwrite(STDOUT,$temp);
    }

    private function colorString(string $str,int $logLevel)
    {
        switch($logLevel) {
            case self::LOG_LEVEL_INFO:
                $out = "[42m";
                break;
            case self::LOG_LEVEL_NOTICE:
                $out = "[43m";
                break;
            case self::LOG_LEVEL_WARNING:
                $out = "[45m";
                break;
            case self::LOG_LEVEL_ERROR:
                $out = "[41m";
                break;
            default:
                $out = "[42m";
                break;
        }
        return chr(27) . "$out" . "{$str}" . chr(27) . "[0m";
    }

    private function levelMap(int $level)
    {
        switch ($level)
        {
            case self::LOG_LEVEL_INFO:
                return 'INFO';
            case self::LOG_LEVEL_NOTICE:
                return 'NOTICE';
            case self::LOG_LEVEL_WARNING:
                return 'WARNING';
            case self::LOG_LEVEL_ERROR:
                return 'ERROR';
            default:
                return 'UNKNOWN';
        }
    }
}